package com.athui.utils.common;

import com.athui.bean.config.ConnectInfo;
import com.athui.enums.DataRegularEnums;
import com.athui.enums.DriverEnums;
import com.athui.enums.FileProtocolEnums;
import org.apache.flink.api.java.tuple.Tuple2;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.stream.Stream;

/**
 * @description: TODO 配置文件加载
 * @autor: zhangzhonghui
 * @create: 2024-08-05 18:18
 * @Version: 1.0
 */
public class ConfigureUtils {

    private static Map<String, Object> yamlMap = null;
    private static  SAXReader saxReader = new SAXReader();

    static {
        InputStream resourceAsStream = ConfigureUtils.class.getClassLoader().getResourceAsStream("application.yaml");
        if (resourceAsStream != null) {
            Yaml yaml = new Yaml();
            yamlMap= yaml.load(resourceAsStream);
            try {
                resourceAsStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @description: TODO 加载数据库连接的配置文件
     * 将数据转换成 ConnectInfo 对象
     * @author: 阿辉大人
     * @param: serverName 服务名称，参考 database-connect-config.yml
     * @return: com.athui.bean.ConnectInfo
     * @create: 2024/8/5 18:49
     * @version: 1.0
    **/
    public static  ConnectInfo getServer(String serverName){

        Map<String, Object> serverMap= (Map<String, Object>)yamlMap.get("server");
        Map<String, Object> config = (Map<String, Object>)serverMap.get(serverName);

        ConnectInfo connectInfo = new ConnectInfo();
        connectInfo.setHost(String.valueOf(config.get("host")));
        connectInfo.setPort(Integer.parseInt(String.valueOf(config.get("port"))));
        connectInfo.setDatabase(String.valueOf(config.get("database")) );
        connectInfo.setUsername(String.valueOf(config.get("username")));
        connectInfo.setPassword(String.valueOf(config.get("password")));
        connectInfo.setDriver(DriverEnums.valueOf(String.valueOf(config.get("type"))));

        return connectInfo;

    }

    /**
     * @description: TODO Auto-generated method stub
     * @author: 阿辉大人
     * @param: line sql 语句
     * @param: params sql 参数
     * @return: java.lang.String
     * @create: 2024/8/6 00:13
     * @version: 1.0
    **/
    public static String paramsReplace(String line, Map<String, Object> params){
        if (params ==null || params.isEmpty()){
            return line;
        }
        // 创建匹配器
        Matcher matcher = DataRegularEnums.TEXT_SQL_PARAMS_PATTERN.getValue().matcher(line);

        while (matcher.find()) {
            // 提取占位符内部的值
            String key = matcher.group(1);
            Object value = params.get(key);
            if (value != null) {
                line = line.replace(String.format("${%s}",key), String.valueOf(value));
            }

        }

        return line;
    }
    public static StringBuffer mapperParser(String id){
        return mapperParser(id,null);
    }

    /**
     * @description: TODO 解析 mapper.xml 中的 sql 语句
     * @author: 阿辉大人
     * @param: id mapper.xml 中的 id
     * @param: params sql 参数
     * @return: java.lang.StringBuffer
     * @create: 2024/8/6 00:12
     * @version: 1.0
    **/
    public static StringBuffer mapperParser(String id,Map<String,Object> params){
        Map<String, Object> profileMap= (Map<String, Object>)yamlMap.get("profile");
        String mapperPath = String.valueOf(profileMap.get("mapper_path"));

        Tuple2<FileProtocolEnums, String> fileProtocol = detectProtocol(mapperPath);

        if (FileProtocolEnums.FILE.equals(fileProtocol.f0)){
            try (Stream<Path> pathStream = Files.walk(Paths.get(fileProtocol.f1))) {
                return  pathStream.filter(path -> DataRegularEnums.TEXT_XML_PATTERN.getValue().matcher(path.getFileName().toString()).matches())
                        .map(path -> mapperParser(path.toFile(), id, params))
                        .filter(Objects::nonNull)
                        .reduce((first, second) -> second)
                        .get();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return null;
    }


    private static StringBuffer mapperParser(File file, String id,Map<String,Object> params){

        try {
            Document document = saxReader.read(file);
            Element rootElement = document.getRootElement();

            for (Object obj : rootElement.elements("select")) {
                Element selectElement = (Element)obj;

                if(selectElement.attributeValue("id").equals(id)){

                    StringBuffer sqlBuffer = new StringBuffer();
                    Arrays.stream(selectElement.getText().split("\n"))
                            // 过滤前后空白符
                            .map(String::trim)
                            // 过滤空行
                            .filter(line -> !line.trim().isEmpty())
                            // 过滤注释
                            .filter(line -> !line.startsWith("--"))
                            // sql 参数替换
                            .map(line -> paramsReplace(line,params))
                            .forEach(line -> sqlBuffer.append(line).append("\n"));

                    return sqlBuffer;
                }
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static Tuple2<FileProtocolEnums, String> detectProtocol(String filePath) {
        // 使用 URI 解析文件路径
        URI uri = URI.create(filePath);
        FileProtocolEnums scheme = FileProtocolEnums.get(uri.getScheme());
        String path = uri.getPath();
        return Tuple2.of(scheme, path);
    }

}
